package com.peas.platform.module.icims.base.sys.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import com.peas.platform.common.core.dto.ResponseDto;
import com.peas.platform.common.core.enums.BaseEnum;
import com.peas.platform.common.core.utils.MultipartFileUtil;
import com.peas.platform.module.icims.base.mdm.enums.FileType;
import com.peas.platform.module.icims.base.sys.api.resp.ExcelResp;
import com.peas.platform.module.icims.base.sys.api.resp.ImageResp;
import com.peas.platform.module.icims.base.sys.api.resp.InvoiceResp;
import com.peas.platform.module.icims.base.sys.component.ExcelExtractor;
import com.peas.platform.module.icims.base.sys.component.ImageExtractor;
import com.peas.platform.module.icims.base.sys.component.InvoiceExtractor;
import com.peas.platform.module.icims.base.sys.controller.vo.AttachmentVo;
import com.peas.platform.module.icims.base.sys.dto.AttachmentDto;
import com.peas.platform.module.icims.base.sys.service.AttachmentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipOutputStream;

@Api(tags = "自定义接口-附件相关接口(包含上传下载)")
@RestController
@RequestMapping("/api/v1/customAttachment")
@Slf4j
public class CustomAttachmentController {

    @Resource
    private HttpServletRequest request;
    @Resource
    private HttpServletResponse response;

    @Resource
    private AttachmentService attachmentService;
    @Resource
    private InvoiceExtractor invoiceExtractor;
    @Resource
    private ImageExtractor imageExtractor;
    @Resource
    private ExcelExtractor excelExtractor;

    @ApiOperation(value = "发票解析接口")
    @GetMapping(value = "/extractInvoice/{attachmentId}")
    public ResponseDto<InvoiceResp> extractInvoice(@PathVariable(value = "attachmentId") Long attachmentId) {
        AttachmentDto dto = attachmentService.getById(attachmentId);
        InvoiceResp v = new InvoiceResp();
        try {
            v = invoiceExtractor.extract(dto);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        BeanUtil.copyProperties(dto, v);
        return ResponseDto.getSuccessResponseDto(v);
    }

    @ApiOperation(value = "发票文件上传接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileType", value = "文件类型(支持类型：document)"),
    })
    @PostMapping(value = "/uploadInvoice")
    public ResponseDto<InvoiceResp> uploadInvoice(@RequestPart(value = "file") MultipartFile file,
                                                  @RequestParam(value = "fileType", required = false) String fileType) {
        FileType fileTypeEnum = BaseEnum.key2Enum(FileType.class, fileType);
        if (fileTypeEnum != FileType.document) {
            fileTypeEnum = FileType.document;
        }
        AttachmentDto dto = attachmentService.upload(file, fileTypeEnum);
        InvoiceResp v = new InvoiceResp();
        try {
            v = invoiceExtractor.extract(file);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        BeanUtil.copyProperties(dto, v);
        return ResponseDto.getSuccessResponseDto(v);
    }

    @ApiOperation(value = "图片上传接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileType", value = "文件类型(支持类型：image)"),
    })
    @PostMapping(value = "/uploadImage")
    public ResponseDto<ImageResp> uploadImage(@RequestPart(value = "file") MultipartFile file,
                                              @RequestParam(value = "fileType", required = false) String fileType) {
        FileType fileTypeEnum = BaseEnum.key2Enum(FileType.class, fileType);
        if (fileTypeEnum != FileType.image) {
            fileTypeEnum = FileType.image;
        }
        AttachmentDto dto = attachmentService.upload(file, fileTypeEnum);
        ImageResp v = new ImageResp();
        try {
            v = imageExtractor.extract(file);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        BeanUtil.copyProperties(dto, v);
        return ResponseDto.getSuccessResponseDto(v);
    }

    @ApiOperation(value = "Excel文件上传接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileType", value = "文件类型(支持类型：excel)"),
    })
    @PostMapping(value = "/uploadExcel")
    public ResponseDto<ExcelResp> uploadExcel(@RequestPart(value = "file") MultipartFile file,
                                              @RequestParam(value = "fileType", required = false) String fileType) {
        FileType fileTypeEnum = BaseEnum.key2Enum(FileType.class, fileType);
        if (fileTypeEnum != FileType.excel) {
            fileTypeEnum = FileType.excel;
        }
        AttachmentDto dto = attachmentService.upload(file, fileTypeEnum);
        ExcelResp v = new ExcelResp();
        try {
            v = excelExtractor.extract(file);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        BeanUtil.copyProperties(dto, v);
        return ResponseDto.getSuccessResponseDto(v);
    }

    @ApiOperation(value = "附件上传接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileType", value = "文件类型(支持类型：word,excel,powerpoint,image,voice,video,deploy)"),
    })
    @PostMapping(value = "/upload")
    public ResponseDto<AttachmentVo> upload(@RequestPart(value = "file") MultipartFile file,
                                            @RequestParam(value = "fileType", required = false) String fileType) {
        FileType fileTypeEnum = BaseEnum.key2Enum(FileType.class, fileType);
        AttachmentDto dto = attachmentService.upload(file, fileTypeEnum);
        return ResponseDto.getSuccessResponseDto(BeanUtil.copyProperties(dto, AttachmentVo.class));
    }

    @SneakyThrows
    @ApiOperation(value = "附件下载接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "附件ID"),
    })
    @GetMapping(value = "/download/{id}")
    public void download(@PathVariable("id") Long id) {
        AttachmentDto dto = attachmentService.getById(id);
        Assert.notNull(dto, "找不到附件信息");
        attachmentService.updateById(dto);
        MultipartFileUtil.initDownloadHeader(request, response, dto.getOriginal());
        IoUtil.copy(attachmentService.getObject(dto), response.getOutputStream());
    }

    @SneakyThrows
    @ApiOperation(value = "批量下载附件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "多个附件ID(半角逗号分隔)"),
    })
    @GetMapping(value = "/downloads")
    public void downloads(@RequestParam("ids") String ids) {
        List<Long> list = new ArrayList<>();
        for (String id : ids.split(",")) {
            list.add(Long.valueOf(id));
        }
        MultipartFileUtil.initDownloadHeader(request, response, "附件打包下载-" + DateUtil.today() + ".zip");
        ZipOutputStream zip = new ZipOutputStream(response.getOutputStream());
        List<AttachmentDto> attachments = attachmentService.listByIds(list);
        attachmentService.zipFiles(attachments, zip);
    }

    @ApiOperation(value = "网络文件预览")
    @GetMapping(value = "/preview")
    public void preview(@RequestParam(value = "url") String url) {
        try (ServletOutputStream out = response.getOutputStream();
             ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
            //new一个URL对象
            URL connection = new URL(url);
            //打开链接
            HttpURLConnection conn = (HttpURLConnection) connection.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);
            //通过输入流获取图片数据
            InputStream is = conn.getInputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                stream.write(buffer, 0, len);
            }
            out.write(stream.toByteArray());
            stream.flush();
            out.flush();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @SneakyThrows
    @ApiOperation(value = "文件预览")
    @GetMapping(value = "/preview/{id}")
    public ResponseDto<String> preview(@PathVariable("id") Long id) {
        try (InputStream is = attachmentService.getObject(id)) {
            return ResponseDto.getSuccessResponseDto(Base64.encode(is));
        }
    }

}
